package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.annotation.UserDataIsolation;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.CreateTaskGatherVO;
import com.ruoyi.system.domain.vo.DeviceGatherVO;
import com.ruoyi.system.domain.vo.DeviceHistoryDto;
import com.ruoyi.system.domain.vo.QueryVo;
import com.ruoyi.system.mapper.PointCheckTaskMapper;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.util.*;
import java.util.stream.Collectors;

@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
@Service
@Slf4j
public class PointCheckTaskServiceImpl implements IPointCheckTaskService {
    @Autowired
    private PointCheckTaskMapper pointCheckTaskMapper;
    @Autowired
    private IPointCheckTaskDeviceService pointCheckTaskDeviceService;
    @Autowired
    private IPointCheckDeviceDetailService pointCheckDeviceDetailService;
    @Autowired
    private IPointCheckTaskDealService pointCheckTaskDealService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private IDevicePointCheckConfigService devicePointCheckConfigService;

    /**
     * 定时任务执行flag
     */
    @Value("${scheduledTask.flag:false}")
    private boolean scheduledTaskFlag;

    /**
     * 现场工程师
     */
    @Value("${sysUser.sceneRoleId:102}")
    private Long sceneRoleId;

    /**
     * 巡检工角色Id
     */
    @Value("${sysUser.inspectorRoleId:104}")
    private Long inspectorRoleId;

    @Override
    public List<PointCheckTask> queryList(PointCheckTask pointCheckTask) {
        List<PointCheckTask> pointCheckTasks = pointCheckTaskMapper.queryList(pointCheckTask);
        if (pointCheckTasks.size() == 1 && pointCheckTasks.get(0).getId() == null) {
            pointCheckTasks = new ArrayList<>();
        }
        return pointCheckTasks;
    }

    @Override
    public List<PointCheckTask> queryListProgress(PointCheckTask pointCheckTask) {
        //查询所有异常的检查项
        QueryVo queryVo = new QueryVo();
        List<Map<String, Object>> allErrorItem = pointCheckTaskDeviceService.queryAllErrorItem(queryVo);
        if (CollUtil.isEmpty(allErrorItem)) {
            return new ArrayList<>();
        }
        Set<Integer> taskIds = new HashSet<>();
        for (Map<String, Object> map : allErrorItem) {
            Integer taskId = (Integer) map.get("taskId");
            Integer id = (Integer) map.get("id");
            // String type = (String) map.get("type");
            // String item = (String) map.get("item");
            // String detail = (String) map.get("detail");
//            //TODO 处理特殊情况下数据（波纹管-腐蚀、异常变形）
//            if (StrUtil.equals("波纹管", type) && (StrUtil.equals("腐蚀", item) || StrUtil.equals("异常变形", item))) {
//                if (StrUtil.isNotBlank(detail)) {
//                    JSONObject jsonObject = JSONUtil.parseObj(detail);
//                    Boolean handle = jsonObject.getBool("handle", true);
//                    if (!handle) {
//                        continue;
//                    }
//                }
//            }
            PointCheckTaskDeal deal = new PointCheckTaskDeal();
            deal.setDetailId(id);
            List<PointCheckTaskDeal> pointCheckTaskDealList = pointCheckTaskDealService.queryList(deal);
            //异常但是未处理
            if (CollUtil.isEmpty(pointCheckTaskDealList)) {
                taskIds.add(taskId);
            }
        }
        if (CollUtil.isEmpty(taskIds)) {
            return new ArrayList<>();
        }
        pointCheckTask.setTaskIds(taskIds);
        List<PointCheckTask> pointCheckTasks = pointCheckTaskMapper.queryListProgress(pointCheckTask);
        if (pointCheckTasks.size() == 1 && pointCheckTasks.get(0).getId() == null) {
            pointCheckTasks = new ArrayList<>();
        }
        return pointCheckTasks;
    }

    @Override
//    @UserDataIsolation(tableAlias = "t")
    public PointCheckTask getOne(PointCheckTask pointCheckTask) {
        return pointCheckTaskMapper.getOne(pointCheckTask);
    }


    @Override
    @Transactional
    public Boolean add(PointCheckTask pointCheckTask) {
        boolean flag = pointCheckTaskMapper.add(pointCheckTask) > 0;
        if (flag){
            Integer taskId = pointCheckTask.getId();
            Long companyId = pointCheckTask.getCompanyId();
            String createBy = pointCheckTask.getCreateBy();
            List<String> deviceIds = StrUtil.splitTrim(pointCheckTask.getDeviceIds(), ",");
            for (String deviceId : deviceIds) {
                PointCheckTaskDevice taskDevice = new PointCheckTaskDevice();
                taskDevice.setDeviceId(Convert.toInt(deviceId));
                taskDevice.setTaskId(taskId);
                taskDevice.setCompanyId(companyId);
                taskDevice.setCreateBy(createBy);
                taskDevice.setCreateTime(new Date());
                pointCheckTaskDeviceService.add(taskDevice);
            }
        }
        return flag;
    }

    @Override
    @Transactional
    public Boolean addV2(PointCheckTask pointCheckTask) {
        boolean flag = pointCheckTaskMapper.add(pointCheckTask) > 0;
        if (flag){
//
            HashMap<String,ArrayList<Integer>> checkConfigList = pointCheckTask.getCheckConfigList();
            //生成任务产品关系
            Integer taskId = pointCheckTask.getId();
            Long companyId = pointCheckTask.getCompanyId();
            String createBy = pointCheckTask.getCreateBy();
            List<String> deviceIds = StrUtil.splitTrim(pointCheckTask.getDeviceIds(), ",");
            for (String deviceId : deviceIds) {
                ArrayList<Integer> arr = checkConfigList.get(deviceId+"");
                ArrayList<DevicePointCheckConfig> list = new ArrayList<>();
                //获取每个 产品点检配置
                for (Integer i:arr
                     ) {
                    QueryVo queryVo = new QueryVo();
                    queryVo.filters.put("id", i);
                    DevicePointCheckConfig devicePointCheckConfig = devicePointCheckConfigService.getOne(queryVo);
                    if(devicePointCheckConfig!=null){
                        list.add(devicePointCheckConfig);
                    }

                }


                PointCheckTaskDevice taskDevice = new PointCheckTaskDevice();
                taskDevice.setDeviceId(Convert.toInt(deviceId));
                taskDevice.setTaskId(taskId);
                taskDevice.setCompanyId(companyId);
                taskDevice.setCreateBy(createBy);
                taskDevice.setCreateTime(new Date());
                pointCheckTaskDeviceService.addV2(taskDevice,list);
            }
        }
        return flag;
    }

    @Override
    @UserDataIsolation
    public Boolean update(PointCheckTask pointCheckTask) {
        return pointCheckTaskMapper.update(pointCheckTask) > 0;
    }

    /**
     * 验证添加指派人角色权限
     * 客户只能添加巡检工角色用户
     * 非客户只能添加现场工程师角色用户
     *
     * @param pointCheckTask
     */
    @Override
    public void checkExecutorStatus(PointCheckTask pointCheckTask){
        String executor = pointCheckTask.getExecutor();
        SysUser sysUser = sysUserService.selectUserByUserName(executor);
        if (sysUser == null){
            throw new CustomException("没有查询到指派人用户信息");
        }
        SysRole roles = sysUser.getRoles().get(0);
        Long deptId = SecurityUtils.getLoginUser().getUser().getDeptId();
        if (sysDeptService.checkIsCustomer(deptId)){
            if (roles.getRoleId().compareTo(inspectorRoleId) != 0){
                throw new CustomException("当前用户只能添加巡检工角色用户");
            }
        }else {
            if (roles.getRoleId().compareTo(sceneRoleId) != 0){
                throw new CustomException("当前用户只能添加现场工程师角色用户");
            }
        }
    }

    @Override
    @Scheduled(cron = "0 0/10 * * * ?")
    public void updatePointCheckTaskStatusCs() {
        if (!scheduledTaskFlag){
            return;
        }
        //获取当时时间
        DateTime date = DateUtil.date();
        QueryVo queryVo = new QueryVo();
        queryVo.filters.put("end_time",date);
        List<PointCheckTaskDevice> pointCheckTaskDeviceList = pointCheckTaskDeviceService.queryAllTaskDevice(queryVo);
        if (CollUtil.isEmpty(pointCheckTaskDeviceList)) {
            return;
        }
        List<PointCheckTaskDevice> updateTaskDevices = pointCheckTaskDeviceList.stream().filter(a -> a.getId() == null).collect(Collectors.toList());
        //没有绑定产品的任务
        if (CollUtil.isNotEmpty(updateTaskDevices)){
            Set<Integer> updateTaskIds = updateTaskDevices.stream().map(PointCheckTaskDevice::getTaskId).collect(Collectors.toSet());
            //更新为已超时状态
            pointCheckTaskMapper.updatePointCheckTaskStatus(updateTaskIds);
        }
        //邦定产品的点检任务
        List<PointCheckTaskDevice> updateTaskDeviceList = pointCheckTaskDeviceList.stream().filter(a -> a.getId() != null).collect(Collectors.toList());
        if (CollUtil.isEmpty(updateTaskDeviceList)){
            return;
        }
        Map<Integer, List<PointCheckTaskDevice>> dataMap = updateTaskDeviceList.stream().collect(Collectors.groupingBy(PointCheckTaskDevice::getTaskId));
        Set<Integer> csList = new HashSet<>();
        Set<Integer> wcList = new HashSet<>();
        for (Map.Entry<Integer, List<PointCheckTaskDevice>> entry : dataMap.entrySet()) {
            Integer taskId = entry.getKey();
            List<PointCheckTaskDevice> taskDevices = entry.getValue();
            List<Integer> collect = taskDevices.stream().map(PointCheckTaskDevice::getReportFlag).collect(Collectors.toList());
            if (!collect.contains(0)) {
                //已完成
                wcList.add(taskId);
            } else {
                PointCheckTaskDevice taskDevice = taskDevices.get(0);
                if (!StrUtil.equals(taskDevice.getStatus(),"2")){
                    csList.add(taskId);
                }
            }
        }
        if (CollUtil.isNotEmpty(csList)) {
            //更新为已超时状态
            pointCheckTaskMapper.updatePointCheckTaskStatus(csList);
        }
        if (CollUtil.isNotEmpty(wcList)) {
            pointCheckTaskMapper.updatePointCheckTaskStatusWc(wcList);
        }
    }


    @Override
    public CreateTaskGatherVO getTaskGather(QueryVo queryVo) {
        Integer id = queryVo.filters.getInteger("id");
        Long companyId = queryVo.filters.getLong("companyId");
        PointCheckTask param = new PointCheckTask();
        param.setId(id);
        param.setCompanyId(companyId);
        PointCheckTask task = pointCheckTaskMapper.getOne(param);
        if (task == null) {
            throw new CustomException("没有查询到对应的计划任务信息");
        }
        CreateTaskGatherVO result = new CreateTaskGatherVO();
        result.setStartTime(task.getStartTime());
        result.setEndTime(task.getEndTime());
        result.setNickName(task.getNickName());
        result.setProjectName(task.getProjectName());
        result.setUseUnit(getUseUnit(task.getDeptId()));
        //查询关联产品信息
        PointCheckTaskDevice taskDeviceParam = new PointCheckTaskDevice();
        taskDeviceParam.setTaskId(task.getId());
        taskDeviceParam.setCompanyId(companyId);
        List<PointCheckTaskDevice> taskDevices = pointCheckTaskDeviceService.queryList(taskDeviceParam);
        if (CollUtil.isEmpty(taskDevices)) {
            return result;
        }
        result.setSumNum(taskDevices.size());
        List<DeviceGatherVO> gatherVOS = new ArrayList<>();
        int number = 0;
        for (PointCheckTaskDevice taskDevice : taskDevices) {
            DeviceGatherVO gatherVO = new DeviceGatherVO();
            // TODO 产品代码就是产品型号，厂家关联产品表
            gatherVO.setCode(taskDevice.getSn());
            gatherVO.setFactory(taskDevice.getManufacturer());
            gatherVO.setPositionNumber(taskDevice.getPositionNumber());
            gatherVO.setName(taskDevice.getName());
            gatherVO.setSystem(taskDevice.getSystem());
            Integer taskDeviceId = taskDevice.getId();
            PointCheckDeviceDetail deviceDetail = new PointCheckDeviceDetail();
            deviceDetail.setTaskDeviceId(taskDeviceId);
            List<PointCheckDeviceDetail> deviceDetails = pointCheckDeviceDetailService.queryList(deviceDetail);
            if (CollUtil.isEmpty(deviceDetails) || CollUtil.isEmpty(deviceDetails.stream().filter(a -> StrUtil.isNotBlank(a.getStatus())).collect(Collectors.toList()))) {
                gatherVO.setStatus("未点检");
                gatherVOS.add(gatherVO);
                continue;
            }
            Collections.sort(deviceDetails, new Comparator<PointCheckDeviceDetail>() {
                @Override
                public int compare(PointCheckDeviceDetail o1, PointCheckDeviceDetail o2) {
                    return o2.getCreateTime().compareTo(o1.getCreateTime());
                }
            });
            gatherVO.setLastTime(deviceDetails.get(0).getCreateTime());
            List<PointCheckDeviceDetail> collect = deviceDetails.stream().filter(a -> StrUtil.isNotBlank(a.getStatus())).collect(Collectors.toList());
            Map<String, List<PointCheckDeviceDetail>> listMap = collect.stream().collect(Collectors.groupingBy(PointCheckDeviceDetail::getStatus));
            List<PointCheckDeviceDetail> details = listMap.get("异常");
            if (CollUtil.isEmpty(details)) {
                gatherVO.setStatus("正常");
                gatherVOS.add(gatherVO);
                continue;
            }
            gatherVO.setStatus("异常");
            List<Map<String, Object>> errorData = new ArrayList<>();
            for (PointCheckDeviceDetail deviceDetail1 : details) {
                String type = deviceDetail1.getType();
                String item = deviceDetail1.getItem();
                String str = type + "-" + item;
                Map<String, Object> map = new HashMap<>();
                map.put("data", str);
                map.put("isDeal", deviceDetail1.isDeal());
                errorData.add(map);
            }
            gatherVO.setErrorData(errorData);
            gatherVOS.add(gatherVO);
            number++;
        }
        result.setAbnormalNum(number);
        result.setDeviceGatherVOS(gatherVOS);
        return result;
    }

    @Override
    public List<DeviceHistoryDto> getDeviceHistory(QueryVo queryVo) {
        String sn = queryVo.filters.getString("sn");
        Long deptId = queryVo.filters.getLong("dept_id");
        Long companyId = queryVo.filters.getLong("company_id");
        if (StrUtil.isBlank(sn)) {
            return new ArrayList<>();
        }
        //判断当前用户是否是客户公司
        boolean flag = sysDeptService.checkIsCustomer(deptId);
        List<DeviceHistoryDto> deviceHistoryDtos = new ArrayList<>();
        if (flag){
            //获取客户公司Id
            Long customerId = sysDeptService.getCustomerId(deptId);
            //查询该客户公司下面所有的用户信息
            List<SysUser> sysUsers = sysUserService.queryUserInfo(customerId);
            if (CollUtil.isEmpty(sysUsers)){
                return new ArrayList<>();
            }
            Set<String> userNames = sysUsers.stream().map(SysUser::getUserName).collect(Collectors.toSet());
            deviceHistoryDtos = pointCheckTaskMapper.queryTaskDetailBySn(companyId,sn,userNames);
        }else {
            deviceHistoryDtos = pointCheckTaskMapper.queryTaskDetailBySn(companyId,sn,null);
        }
        if (CollUtil.isEmpty(deviceHistoryDtos)){
            return new ArrayList<>();
        }
        List<DeviceHistoryDto> result = new ArrayList<>();
        for (DeviceHistoryDto dto : deviceHistoryDtos) {
            queryVo.filters.clear();
            queryVo.filters.put("task_device_id",dto.getTaskDeviceId());
            queryVo.filters.put("company_id",companyId);
            List<DeviceHistoryDto> deviceHistoryDtoList = pointCheckTaskMapper.queryDeviceHistory(queryVo);
            if (CollUtil.isEmpty(deviceHistoryDtoList)){
                continue;
            }
            for (DeviceHistoryDto historyDto : deviceHistoryDtoList) {
               historyDto.setDeviceName(dto.getDeviceName());
               historyDto.setSn(dto.getSn());
               historyDto.setName(dto.getName());
               historyDto.setStartTime(dto.getStartTime());
               historyDto.setEndTime(dto.getEndTime());
               historyDto.setNickName(dto.getNickName());
               historyDto.setTaskDeviceId(dto.getTaskDeviceId());
               result.add(historyDto);
            }
        }
        log.info("产品历史汇总记录总条数：{}",result.size());
        if (CollUtil.isEmpty(result)){
            return new ArrayList<>();
        }
        Collections.sort(result, new Comparator<DeviceHistoryDto>() {
            @Override
            public int compare(DeviceHistoryDto o1, DeviceHistoryDto o2) {
                return o2.getTime().compareTo(o1.getTime());
            }
        });
        return result;
    }

    @Override
    public List<Map<String, Object>> getDeviceEnum(QueryVo queryVo) {
        Integer projectId = queryVo.filters.getInteger("project_id");
        if (projectId == null){
            return new ArrayList<>();
        }
        return pointCheckTaskMapper.getDeviceEnum(queryVo);
    }

    /**
     * 获取客户名称(多级)
     *
     * @param deptId
     * @return
     */
    private String getUseUnit(Long deptId) {
        if (deptId == null) {
            return null;
        }
        SysDept sysDept = sysDeptService.selectDeptById(deptId);
        if (sysDept == null) {
            throw new CustomException("当前任务所属项目的客户公司不存在！");
        }
        if (sysDept.getParentId() == 0 || sysDept.getIsCustomer() == 1) {
            return sysDept.getDeptName();
        }
        List<String> deptIds = StrUtil.splitTrim(sysDept.getAncestors(), ",");
        List<String> resultList = new ArrayList<>();
        resultList.add(sysDept.getDeptName());
        for (int i = deptIds.size() - 1; i > 0; i--) {
            String deptIdStr = deptIds.get(i);
            SysDept dept = sysDeptService.selectDeptById(Convert.toLong(deptIdStr));
            resultList.add(0, dept.getDeptName());
            if (dept.getIsCustomer() == 1) {
                break;
            }
        }
        return StrUtil.join("-", resultList);
    }
}
